/************************************************************
 * Copyright (c) 2010 Georg Fritzsche
 *
 * This project is licensed under the "New BSD License": 
 * http://www.opensource.org/licenses/bsd-license.php
 ***********************************************************/

#include <string>
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <iomanip>

#include <boost/make_shared.hpp>

#include <fmod.hpp>
#include <fmod_errors.h>

#include "player.h"
#include "track.h"
#include "fmod_util.h"
#include "config.h"


namespace 
{
    Player::TrackPtrVector load_tracks(const Config& config, const boost::shared_ptr<AudioSystem>& system)
    {
        typedef std::vector<std::string> PathList;
        PathList paths;
	    std::ifstream playlistFile;
	    char buf[4080];
	    const int bufsize = sizeof(buf) / sizeof(buf[0]);

	    playlistFile.open(config.playlistPath().c_str());
        if (!playlistFile.is_open()) {
            throw std::runtime_error("failed to open playlist");
        }

	    while(!playlistFile.eof())
	    {
		    playlistFile.getline(buf, bufsize);
		    std::string s = buf;
		    std::cout << s << std::endl;

		    if(s.size() < 1)      continue;
		    if(*s.begin() == '#') continue;

            paths.push_back(s);
	    }

        if (paths.size() < 1) {
            throw std::logic_error("no tracks in playlist");
        }

	    playlistFile.close();

        typedef std::map<std::string, boost::shared_ptr<Track> > TrackMap;
        TrackMap trackMap;
        Player::TrackPtrVector tracks;

        for (PathList::const_iterator it = paths.begin(); it != paths.end(); ++it)
        {
            TrackMap::const_iterator track_it = trackMap.find(*it);
            if (track_it == trackMap.end()) {
                track_it = trackMap.insert(
                               trackMap.begin(), 
                               std::make_pair(*it, boost::make_shared<Track>(*it, system, config.streamSamples()))
                           );
            }

            tracks.push_back(track_it->second);
        }
        
	    return tracks;
    }
}

Player::Player(const boost::shared_ptr<AudioSystem>& system, const Config& config)
  : m_tracks(load_tracks(config, system))
  , m_index(index_no_track)
{

}

Player::~Player()
{
    for (size_t i=0; i<m_tracks.size(); ++i) {
        m_tracks[i]->stop();
    }
}

bool Player::valid_index(index_type index) const
{
    return (index >= 0) && (index < m_tracks.size());
}

bool Player::at_end(index_type index) const
{
    return (index == (m_tracks.size() + 1));
}

void Player::play(index_type index)
{
    m_index = index;
    m_tracks[index]->play();

    std::cout << "playing #" 
              << std::setw(2) << std::setfill('0') << (m_index + 1)
              << std::endl;
}

void Player::stop()
{
    if (valid_index(m_index)) {
        m_tracks[m_index]->stop();
    }
}

void Player::next()
{
    stop();

    if ((m_index == index_no_track) && valid_index(0)) {
        play(0);
    } else if (valid_index(++m_index)) {
        play(m_index);
    }
}

void Player::reset()
{
    if (valid_index(m_index)) {
        m_tracks[m_index]->stop();
    }

    m_index = index_no_track;
    std::cout << "tracks reset" << std::endl;
}
